package arithmetic.thread.bolckqueen;

import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

import org.junit.jupiter.api.Test;

/**
 * @author jiangfeng on 2022/4/10
 */
public class BlockQueenTest {

    /**
     * 单个消费者, 单个生产者
     * @param blockQueen
     */
    private void execTestBlockQueen(MyBlockQueenInterface<Integer> blockQueen) {
        blockQueen.put(1);
        // 生产者 一秒一个 总共10个
        Thread productor = new Thread(() -> {
            for (int i = 2; i < 11; i++) {
                blockQueen.put(i);
                System.out.println(Thread.currentThread().getName() + " add:" + i);
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "productor");
        productor.start();

        // 消费者 有我就消费 也只消费10个
        Thread consumer = new Thread(() -> {
            for (int i = 2; i < 110; i++) {
                Integer take = blockQueen.take();
                System.out.println(Thread.currentThread().getName() + " take:" + take);
                /*try {
                    //TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }*/
            }
        }, "consumer");
        consumer.start();


        try {
            // Thread.currentThread().join(); 错误的写法
            //Thread.sleep(10000); low的写法

            // 等待两个线程都完成了就可以不阻塞了
            productor.join();
            consumer.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("---单个消费者:测试完毕---");
    }


    private void execTestBlockQueen2(MyBlockQueenInterface<Integer> blockQueen, int size) {
        //blockQueen.put(1);
        //System.out.println("先放1个元素:---");

        CopyOnWriteArrayList<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
        for (int i = 0; i < size; i++){
            copyOnWriteArrayList.add(i);
        }

        // 生产者 一秒一个 总共10个
        Thread productor = new Thread(() -> {
            while (!copyOnWriteArrayList.isEmpty()){
                Integer remove = copyOnWriteArrayList.remove(0);
                blockQueen.put(remove);

                System.out.println(Thread.currentThread().getName() + " add:" + remove);
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "productor");
        Thread productor1 = new Thread(() -> {
            while (!copyOnWriteArrayList.isEmpty()){
                Integer remove = copyOnWriteArrayList.remove(0);
                blockQueen.put(remove);

                System.out.println(Thread.currentThread().getName() + " add:" + remove);
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "productor1");
        productor.start();
        productor1.start();

        // 消费者 有我就消费 也只消费10个
        Thread consumer = new Thread(() -> {
            while (!copyOnWriteArrayList.isEmpty()){
                Integer take = blockQueen.take();
                System.out.println(Thread.currentThread().getName() + " take:" + take);
            }
        }, "consumer");
        Thread consumer1 = new Thread(() -> {
            while (!copyOnWriteArrayList.isEmpty()){
                Integer take = blockQueen.take();
                System.out.println(Thread.currentThread().getName() + " take:" + take);
            }

        }, "consumer1");
        consumer.start();
        consumer1.start();


        try {
            // Thread.currentThread().join(); 错误的写法
            //Thread.sleep(10000); low的写法

            // 等待两个线程都完成了就可以不阻塞了
            productor.join();
            productor1.join();
            consumer.join();
            consumer1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("---两个生产消费 测试完毕---");
    }

    /**
     * 测试 synchronize写法的 阻塞队列
     */
    @Test
    public void test1() throws InterruptedException {
        MyBlockQueen<Integer> blockQueen = new MyBlockQueen<Integer>(10);
        execTestBlockQueen(blockQueen);

    }

    /**
     * lock 加 condition await,signal来切换线程
     */
    @Test
    public void test2() throws InterruptedException {
        MyBlockQueen2<Integer> blockQueen = new MyBlockQueen2<Integer>(10);
        execTestBlockQueen(blockQueen);

    }

    /**
     * todo 多生产消费者会卡克 ,主要是生产者和消费者 都完成了任务才能一起退出.
     * lock 加 多条件写法 condition await,signal来切换线程
     */
    @Test
    public void test3() throws InterruptedException {
        MyBlockQueenInterface<Integer> blockQueen = new MyBlockQueen3<Integer>(1);
        //execTestBlockQueen(blockQueen);
        execTestBlockQueen2(blockQueen,10);

    }

    /**
     * todo 有卡壳问题
     *  LockSupport park 和 unpark
     * @throws InterruptedException
     */
    @Test
    public void test4() throws InterruptedException {
        MyBlockQueenInterface<Integer> blockQueen = new MyBlockQueen4<Integer>(1);
        //execTestBlockQueen(blockQueen);
        execTestBlockQueen2(blockQueen,10);

    }


}
